package sys

import (
	"errors"
	"faker/project-public/global"
	"faker/project-public/model/sys"
	"faker/project-public/request"
	"gorm.io/gorm"
	"strings"
	"time"
)

var ErrRoleExistence = errors.New("存在相同角色")

type RoleService struct {
}

// CreateRole 创建权限
func (roleService *RoleService) CreateRole(r sys.SysRole) (userRole sys.SysRole, err error) {
	var role sys.SysRole
	if !errors.Is(global.FAKER_DB.Where("name = ?", r.Name).First(&role).Error, gorm.ErrRecordNotFound) { // 判断角色名是否重复
		return userRole, ErrRoleExistence
	}
	err = global.FAKER_DB.Create(&r).Error
	return r, err
}

// GetRoleInfo 获取角色信息
func (roleService *RoleService) GetRoleInfo(id int) (roleInfo sys.SysRole, err error) {
	err = global.FAKER_DB.Where("role_id = ?", id).First(&roleInfo).Error
	return roleInfo, err
}

// GetRoleList 获取角色列表
func (roleService *RoleService) GetRoleList(pageInfo request.PageInfo) (list interface{}, total int64, err error) {
	limit := pageInfo.PageSize
	offset := pageInfo.PageSize * (pageInfo.Page - 1)
	db := global.FAKER_DB.Model(&sys.SysRole{})
	var roleList []sys.SysRole
	err = db.Count(&total).Error
	if err != nil {
		return
	}
	err = db.Limit(limit).Offset(offset).Preload("Users").Preload("Rules").Find(&roleList).Error
	// 提取每个Item的Title值并存储到新的字段中
	for i, items := range roleList {
		var titles []string
		for _, item := range items.Rules {
			titles = append(titles, item.Title)
		}
		roleList[i].Titles = strings.Join(titles, ",")
	}
	return roleList, total, err
}

// SetRole 更新角色
func (roleService *RoleService) SetRole(info sys.SysRole) (err error) {
	var setRole sys.SysRole
	db := global.FAKER_DB.Model(&setRole)
	err = CheckDuplicateRoleName(info)
	if err != nil {
		// 处理角色名重复的情况
		return errors.New("存在重复name，请修改name")
	}
	updateData := map[string]interface{}{"name": info.Name, "update_time": time.Now().Unix()}
	err = db.Where("role_id = ?", info.RoleId).Updates(updateData).Error
	if err != nil {
		return errors.New("更新角色失败")
	}
	return err
}

func CheckDuplicateRoleName(info sys.SysRole) error {
	var setRole sys.SysRole
	db := global.FAKER_DB.Model(&setRole)
	err := db.Where("role_id = ?", info.RoleId).Where("name = ?", info.Name).First(&setRole).Error
	if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
		// 查询过程中发生其他错误
		return err
	}
	if setRole.RoleId != 0 {
		// 角色名重复
		return errors.New("角色名重复")
	}
	return nil
}

// DeleteRole 删除角色
func (roleService *RoleService) DeleteRole(id int) (err error) {
	var roleInfo sys.SysRole
	err = global.FAKER_DB.Where("role_id = ?", id).First(&roleInfo).Error
	if err != nil {
		return errors.New("无此路径")
	}
	//查询用户有没有此角色，用的话，让他修改以后才能删除
	var userRole sys.SysUserRole
	err = global.FAKER_DB.Where("sys_role_id = ?", id).First(&userRole).Error
	if !errors.Is(err, gorm.ErrRecordNotFound) {
		return errors.New("角色已经被使用")
	}
	err = global.FAKER_DB.Where("role_id = ?", id).Delete(&roleInfo).Error
	return err
}

// GetRoles 获取角色全部列表
func (roleService *RoleService) GetRoles() (list interface{}, err error) {
	db := global.FAKER_DB.Model(&sys.SysRole{})
	var roleList []sys.SysRole
	err = db.Select("role_id,name").Find(&roleList).Error
	return roleList, err
}

// GetRoleRules 获取角色全部功能列表
func (roleService *RoleService) GetRoleRules(id int) (list interface{}, err error) {
	db := global.FAKER_DB.Model(&sys.SysRoleAccess{})
	var roleRuleList []sys.SysRoleAccess
	err = db.Select("sys_role_role_id,sys_rule_id").Where("sys_role_role_id = ?", id).Find(&roleRuleList).Error

	var ruleIds []uint // 定义一个切片来存储 sys_rule_id
	for _, item := range roleRuleList {
		ruleIds = append(ruleIds, item.SysRuleId) // 将 sys_rule_id 添加到切片中
	}
	return ruleIds, err
}

// SetRoleRules 分配权限
func (roleService *RoleService) SetRoleRules(id int, ids []uint) (err error) {
	var roleAccess sys.SysRoleAccess
	db := global.FAKER_DB.Model(&sys.SysRoleAccess{})
	db.Where("sys_role_role_id = ?", id).Delete(&roleAccess)
	var ruleData []sys.SysRoleAccess
	for _, value := range ids {
		newRoleAccess := sys.SysRoleAccess{
			SysRoleId: uint(id),
			SysRuleId: value,
		}
		ruleData = append(ruleData, newRoleAccess)
	}
	err = global.FAKER_DB.Create(&ruleData).Error
	return err
}
